package com.fxm.service.impl;

import com.fxm.constant.RedisConstants;
import com.fxm.domain.User;
import com.fxm.returns.RespCode;
import com.fxm.returns.RespEntity;
import com.fxm.service.SignInService;
import com.fxm.service.UserService;
import com.fxm.utils.RedisUtil;
import com.fxm.utils.TimeRatioUtil;
import com.fxm.vo.param.IntegralParam;
import com.fxm.vo.param.OpenParam;
import com.fxm.vo.result.SignResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;

/**
 * <p>
 * 用户签到信息 服务实现类
 * </p>
 *
 * @author fxm
 * @since 2021-01-04
 */
@Slf4j
@Service
public class SignInServiceImpl implements SignInService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserService userService;

    @Override
    public RespEntity<SignResult> getSignInValue(OpenParam openParam) {
        if (Objects.isNull(openParam)) {
            log.info("参数为空，不符合要求");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        String count = redisUtil.hget(RedisConstants.key.SIGN_IN, openParam.getOpenid());
        //累计签到天数
        count = StringUtils.isBlank(count) ? "0" : count;
        //今日签到可获积分
        Integer integral = rewardPoints(Integer.parseInt(count));
        log.info(openParam.getOpenid() + "用户的签到次数为，count={}", count);
        return new RespEntity(RespCode.SUCCESS, new SignResult(integral, Integer.parseInt(count)));
    }

    @Override
    public RespEntity<SignResult> signIn(OpenParam openParam) {
        if (Objects.isNull(openParam)) {
            log.info("参数为空，不符合要求");
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        //先查询之前的签到次数
        RespEntity<SignResult> respEntity = getSignInValue(openParam);
        if (Objects.isNull(respEntity.getData())) {
            return new RespEntity(RespCode.PARAMETERS_ERROR);
        }
        SignResult signResult = (SignResult) respEntity.getData();
        //累计签到次数
        int count = signResult.getDays() + 1;
        //当前时间到第二天凌晨的秒数
        Long nextEarlyMorningSeconds = TimeRatioUtil.getSecondsNextEarlyMorning();
        //新增或覆盖原有缓存记录并设置过期时间
        redisUtil.hdel(RedisConstants.key.SIGN_IN, openParam.getOpenid());
        redisUtil.hset(RedisConstants.key.SIGN_IN, openParam.getOpenid(), String.valueOf(count), nextEarlyMorningSeconds);
        log.info("签到成功，签到次数为，count={}", count);
        //当前时间到今天凌晨的秒数
        Long todayEarlyMorningSeconds = TimeRatioUtil.getSecondsTodayEarlyMorning();
        //标记为已签到并设置过期时间
        redisUtil.hdel(RedisConstants.key.IS_SIGN, openParam.getOpenid());
        redisUtil.hset(RedisConstants.key.IS_SIGN, openParam.getOpenid(), "sign", todayEarlyMorningSeconds);
        //签到积分奖励
        Integer integral = rewardPoints(count);
        log.info("今日签到可获积分为，integral={}", integral);
        //更新用户积分值
        updateUserIntegral(integral, openParam.getOpenid());
        return new RespEntity(RespCode.SUCCESS, new SignResult(integral, count));
    }

    /**
     * 更新用户积分
     * @param integral
     * @param openid
     */
    private void updateUserIntegral(Integer integral, String openid) {
        IntegralParam integralParam = new IntegralParam();
        integralParam.setOpenid(openid);
        RespEntity<User> respEntity = userService.getUserByOpenId(new OpenParam(openid));
        if (Objects.nonNull(respEntity.getData())) {
            User user = (User) respEntity.getData();
            integralParam.setNumber(user.getIntegral() + integral);
            userService.updateUser(integralParam);
        }
    }

    /**
     * 积分奖励规则
     * @param count
     * @return
     */
    private Integer rewardPoints(Integer count) {
        Integer integral = 0;
        switch (count) {
            case 1 : integral = 50; break;
            case 2 : integral = 100; break;
            case 3 : integral = 200; break;
            case 4 : integral = 300; break;
            case 5 : integral = 400; break;
            case 6 : integral = 500; break;
            case 7 : integral = 1000; break;
            default: integral = 1000;
        }
        return integral;
    }
}
